{"id":37,"library":"lemonsqueezy (no official Python SDK)","title":"Lemon Squeezy","description":"Merchant of record platform for digital products. Acquired by Stripe in October 2024. Being absorbed into 'Stripe Managed Payments' (announced May 2025, private preview). No official Python SDK exists — only community-maintained libraries. REST API uses JSON:API spec with Bearer auth.","status":"deprecated","version":"REST API v1 (no official Python SDK)","language":"python","source_language":"en","source_url":"https://docs.lemonsqueezy.com/api","tags":["payments","merchant-of-record","digital-products","stripe","billing","python"],"install":[{"cmd":"pip install requests","lang":"bash","label":"Python (use direct REST calls — no official SDK)"}],"dependencies":[],"imports":[{"note":"No official Python SDK. Any 'lemonsqueezy' PyPI package is unofficial/community-maintained. Use requests or httpx against the REST API directly.","wrong":"from lemonsqueezy import Client","symbol":"API client","correct":"import requests\n\nheaders = {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Accept': 'application/vnd.api+json',\n    'Content-Type': 'application/vnd.api+json'\n}\nresponse = requests.get('https://api.lemonsqueezy.com/v1/products', headers=headers)\n"}],"quickstart":{"code":"import requests\nimport os\n\nAPI_KEY = os.getenv('LEMON_SQUEEZY_API_KEY')\nBASE_URL = 'https://api.lemonsqueezy.com/v1'\n\nheaders = {\n    'Authorization': f'Bearer {API_KEY}',\n    'Accept': 'application/vnd.api+json',\n    'Content-Type': 'application/vnd.api+json'\n}\n\n# List products\nresp = requests.get(f'{BASE_URL}/products', headers=headers)\nproducts = resp.json()['data']\nfor product in products:\n    print(product['id'], product['attributes']['name'])\n\n# Verify webhook signature (HMAC-SHA256)\nimport hmac\nimport hashlib\n\ndef verify_webhook(payload: bytes, signature: str, secret: str) -> bool:\n    expected = hmac.new(\n        secret.encode(),\n        payload,\n        hashlib.sha256\n    ).hexdigest()\n    return hmac.compare_digest(expected, signature)","lang":"python","description":"Direct REST API usage. Response follows JSON:API spec — data is in response['data'], not response directly."},"warnings":[{"fix":"For new projects, join the Stripe Managed Payments waitlist. For existing Lemon Squeezy integrations, no immediate action needed — Lemon Squeezy API continues operating.","message":"Lemon Squeezy was acquired by Stripe in October 2024. As of May 2025, Stripe announced 'Stripe Managed Payments' as the successor merchant of record product. Lemon Squeezy's API may be deprecated or migrated to Stripe infrastructure in the future. New integrations should evaluate Stripe Managed Payments (waitlist) instead.","severity":"breaking","affected_versions":"all"},{"fix":"Use requests or httpx against the REST API directly. The API is stable and documented at docs.lemonsqueezy.com/api.","message":"No official Python SDK exists. All PyPI packages named 'lemonsqueezy*' are unofficial, may be abandoned, and have no support from Lemon Squeezy / Stripe.","severity":"breaking","affected_versions":"all"},{"fix":"Access data at response.json()['data'] for single resources or list responses. Meta and links are at the top level.","message":"The Lemon Squeezy API follows JSON:API spec. Response payload is wrapped: response['data'] contains the resource(s), not the top-level response. Code accessing response['products'] or response['id'] directly fails.","severity":"gotcha","affected_versions":"all"},{"fix":"Set headers: {'Accept': 'application/vnd.api+json', 'Content-Type': 'application/vnd.api+json'}","message":"Both Accept and Content-Type headers must be 'application/vnd.api+json', not 'application/json'. Sending standard JSON headers returns 406 Not Acceptable.","severity":"gotcha","affected_versions":"all"},{"fix":"Create separate API keys for test and live modes from Settings > API.","message":"Lemon Squeezy has Test mode (separate from live). Test mode API keys start with a different prefix. Using a live key in Test mode or vice versa will access production data unexpectedly.","severity":"gotcha","affected_versions":"all"},{"fix":"Address pip warnings by using a virtual environment (e.g., `python -m venv .venv && source .venv/bin/activate`) and consider updating pip (`pip install --upgrade pip`). If running in a container, ensure appropriate user permissions are used instead of root for package installations.","message":"The `pip` package manager issued warnings during installation/operation, specifically regarding running as the 'root' user and an available update. These are not directly related to the Lemon Squeezy API integration itself but rather the Python environment setup.","severity":"gotcha","affected_versions":"all"}],"env_vars":{"optional":[{"name":"LEMON_SQUEEZY_WEBHOOK_SECRET","note":"Webhook signing secret for HMAC-SHA256 verification."}],"required":[{"name":"LEMON_SQUEEZY_API_KEY","note":"API key from Settings > API in Lemon Squeezy dashboard. No standard env var name — check any SDK you use for its expected name."}]},"last_verified":"2026-05-12T05:18:43.269Z","next_check":"2026-06-01T00:00:00.000Z","problems":[{"fix":"Ensure you have created an API key in your Lemon Squeezy dashboard (Settings » API), and include it in your request headers as `Authorization: Bearer YOUR_API_KEY`.","cause":"The API request was made without a valid Bearer authentication token in the Authorization header, or the API key is expired or incorrect.","error":"{\"detail\": \"Unauthenticated.\", \"status\": \"401\", \"title\": \"Unauthorized\"}"},{"fix":"Always check the HTTP status code (`response.status_code`) and raw response text (`response.text`) before attempting `response.json()`. Ensure your requests include `Accept: application/vnd.api+json` and `Content-Type: application/vnd.api+json` headers.","cause":"Your Python code attempted to parse an API response as JSON using `response.json()`, but the response content was not valid JSON (e.g., it was an HTML error page, plain text, or empty). This often occurs if required JSON:API headers (`Accept`, `Content-Type`) are missing or incorrect, or if an invalid endpoint was hit.","error":"json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)"},{"fix":"Consult the Lemon Squeezy API documentation for the specific endpoint to identify all required parameters and their expected data types and formats, then adjust your request payload accordingly.","cause":"The API request failed validation because a required field was either missing from the payload or the provided value was invalid (e.g., wrong data type or format).","error":"422 Unprocessable Entity / A required field was invalid or missing."},{"fix":"Implement exponential backoff or other rate-limiting strategies in your application. Monitor the `X-Ratelimit-Limit` and `X-Ratelimit-Remaining` headers in successful responses to manage your call frequency.","cause":"Your application has exceeded the allowed rate limit for API calls (e.g., 300 requests per minute for the main API).","error":"429 Too Many Requests"}],"ecosystem":"pypi","meta_description":null,"install_score":0,"install_tag":"stale","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null}]},"quickstart_checks":{"last_tested":"2026-05-12","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}